package com.woniuxy.queueProperties;

import com.rabbitmq.client.*;
import com.woniuxy.utils.RabbitConnection;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

/**
 * @Author: linKe
 * @Date: 2022/1/10 16:37
 * @FileName: Consumer
 * @version: 1.0
 * @Description: 消费者处理消息--消费确认ACK
 */
@Log4j2
public class ConsumerEmailQueueProperties {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 连接通道
        Channel channel = RabbitConnection.getConnection().createChannel();
      /*
        主动声明一个非自动删除、非持久的交换，没有额外的参数
        (String exchange, BuiltinExchangeType type)
        参数：
            交易所——交易所的名称
            type – 交换类型
         */
        channel.exchangeDeclare("exchangeQueueProperties", BuiltinExchangeType.TOPIC);

        // 设置队列属性
        Map<String, Object> arguments = new HashMap<>(10);
        // 设置全局消息统一过期时间
        arguments.put("x-message-ttl", 100000);
        // 设置队列最大存放数量   设置队列中存储消息最大数量，超过了最大的数量，继续发送消息，如果有死信队列，进死信；没有死信，消息丢失
        arguments.put("x-max-length", 20);
        channel.queueDeclare("queueEmailTopicTest", true, false, false, arguments);

            /*
            (String queue, String exchange, String routingKey)
            将队列绑定到交换，没有额外的参数。
            参数：
                queue – 队列的名称
                交易所——交易所的名称
                routingKey – 用于绑定的路由键
         */
        channel.queueBind("queueEmailTopicTest", "exchangeQueueProperties", "#.test.#");

        // 第一步：添加限流：指定消费者每次从队列中取几条消息
        channel.basicQos(1);

        channel.basicConsume("queueEmailTopicTest", false, new DefaultConsumer(channel) {
            /**
             * 处理消息的业务代码
             * @param consumerTag 消息标记，系统会自动分配
             * @param envelope  信封，封装和当前消息相关的消息，后面的手动确认要是用
             * @param properties    发送消息时指定的附加属性
             * @param body          消息体
             */
            @SneakyThrows
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // Thread.sleep(5000);
                log.info("body:" + new String(body));
                /*
                第三步： 服务器收到ACK确认消息，才会真正删除队列中的消息
                    确认一条或多条收到的消息。 从AMQP.Basic.GetOk或AMQP.Basic.Deliver方法提供 deliveryTag，其中包含正在确认的接收消息。
                    参数：
                        deliveryTag – 信封的标记
                            收到的AMQP.Basic.GetOk或AMQP.Basic.Deliver的标签
                        multiple –      是否同时确认
                            true 以确认所有消息，包括提供的交付标签；
                            false 仅确认提供的交付标签。
                 */
                    log.info("Ack");
                    channel.basicAck(envelope.getDeliveryTag(), false);
                    log.info("------------------------------------------------");


            }
        });
    }
}
